﻿using System.Reflection;
using System.Runtime.CompilerServices;

namespace ZenSystemService.Api.Common
{
    public static class AutoMapperExtensions
    {
        public static void ConfigAutoMapper(this IServiceCollection services)
        {
            var types = Assembly.GetExecutingAssembly().GetTypes();
            var dtoTypesAll = types.Where(t => t.Namespace != null && t.Namespace.StartsWith("ZenSystemService.Api.DTOs")
                && !Attribute.IsDefined(t, typeof(CompilerGeneratedAttribute), false)
                    && t.IsClass);
            var entityTypesAll = types.Where(t => t.Namespace != null && t.Namespace.StartsWith("ZenSystemService.Api.Entities")
                && !Attribute.IsDefined(t, typeof(CompilerGeneratedAttribute), false)
                    && t.IsClass);


            services.AddAutoMapper(config =>
            {
                foreach (var entityType in entityTypesAll)
                {
                    var dtoTypes = dtoTypesAll.Where(dt => IsMatch(entityType, dt)).ToList();
                    dtoTypes.ForEach(t =>
                    {
                        config.CreateMap(t, entityType).ReverseMap();
                    });
                }
            });
        }

        private static Func<Type, Type, bool> IsMatch = (Type entityType, Type dtoType) =>
        {
            string[] Patterns = {
                "",
                "Create",
                "CreateResult",
                "UpdateResult",
                "CreateRequest",
                "UpdateRequest",
                "QueryResult",
                "LoginResult",
                "AssignResult"
            };
            if (entityType.Name.Length > dtoType.Name.Length)
                return false;
            var findSubstring = dtoType.Name.Substring(entityType.Name.Length);
            if(findSubstring.Length < 3)
                return false;
            findSubstring = findSubstring.Substring(0, findSubstring.Length - 3);
            if (Patterns.Contains(findSubstring))
                return true;
            return false;
        };
    }
}
